package com.songlanyun.modules.payorder.entity;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.type.TypeReference;
import com.songlanyun.common.drive.RootEntity;
import com.songlanyun.common.enums.GoodsConstant;
import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.enums.PartnerTypeConverter;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.DateUtils;
import com.songlanyun.common.utils.custom.ClassConvertUtils;
import com.songlanyun.common.utils.custom.DateCustomUtils;
import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.rabbitmq.util.SpringContextUtil;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Convert;
import javax.persistence.EntityListeners;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 用来聚合支付的订单
 *
 * @author lubo
 * @email sunlightcs@gmail.com
 * @date 2020-11-17 09:16:34
 */
@Data
@TableName("yxt_sale_pay_order")
@EntityListeners(AuditingEntityListener.class)
public class PayOrder extends RootEntity<Long, PayOrder> implements Serializable {
    private static final long serialVersionUID = 1L;
    {
        channelType= OrderConstant.ChannelType.SYSTEM;
    }

    /**
     *
     */
    @TableId
    private Long id;

    /**
     * 支付时用的业务编号
     */
    @NotBlank(message = "支付时用的业务编号不能为空")
    private String code;

    /**
     * 总费用
     */
    private BigDecimal totalAmount;

    /**
     * 总优惠
     */
    private BigDecimal totalReduced;

    /**
     * 实收金额。商家在交易中实际收到的款项，单位为人民币（元），精确到小数点后 2 位
     */
    private BigDecimal receiptAmount;

    /**
     * 用户在交易中支付的金额，单位为人民币（元），精确到小数点后 2 位
     */
    private BigDecimal buyerPayAmount;


    /**
     * 总积分
     */
    private BigDecimal totalPoint = BigDecimal.ZERO;

    /**
     * 是否是积分订单
     */
    private Boolean pointGoods = false;

    /**
     * 是否是后台生成的订单
     */
    private Boolean adminOrder = false;



    /**
     * 支付方式（0余额，1微信，2支付宝，3银行线下）
     */
    private OrderConstant.PayMode payMode;

    /**
     * 在这里是支付渠道
     */
    private OrderConstant.ChannelType channelType;
    /**
     * 成功支付的时间戳
     */
    private Long payTime;
    public void  setPayTime(Long payTime)
    {
        this.payTime= payTime;
        this.formatPayTime = DateCustomUtils.formatToDateTimeString(payTime);
    }
    /**
     * 格式化成功支付的时间
     */
    @TableField(exist =  false)
    private String formatPayTime;

    /**
     * 支付过期时间（时间戳）
     */
    @NotNull(message = "支付过期时间不能为空")
    private Long expiredPayTime;
    public void  setExpiredPayTime(Long expiredPayTime)
    {
        this.expiredPayTime= expiredPayTime;
        this.formatExpiredPayTime = DateCustomUtils.formatToDateTimeString(expiredPayTime);
    }

    /**
     * 格式化支付过期时间（时间戳）
     */
    @TableField(exist =  false)
    private String formatExpiredPayTime;



    /**
     * 0未支付 1支付成功，但业务发生异常需要发起退款 2支付成功，但业务发生异常自款成功 3支付成功，但业务发生异常退款失败 4支付失败 5已支付(已支付成功)
     */
    @Convert(converter = PartnerTypeConverter.class)
    private OrderConstant.PaymentStatus paymentStatus;
    /**
     * 0未关闭,1用户撤销关闭,2商家撤销关闭,3支付过期关闭,4退货成功,5退款成功,6支付成功,但条件已经不允许购买,发生自动退款关闭,7自提过期
     */
    private OrderConstant.CloseMode closeMode;

    /**
     * 第三方支付单号
     */
    private String thirdPayCode = "";
    /**
     * 订单是否已取关闭
     */
    @TableField("`close`")
    private Boolean close = false;

    /**
     * 用户id
     */
    private Long userId;
    /**
     * 创建时间
     */
    private Long createTimeMillis;
    public void  setCreateTimeMillis(Long createTimeMillis)
    {
        this.createTimeMillis= createTimeMillis;
        this.formatCreateTimeMillis = DateCustomUtils.formatToDateTimeString(createTimeMillis);
    }

    /**
     * 格式化创建时间
     */
    @TableField(exist =  false)
    private String formatCreateTimeMillis;





    /**
     * 关闭时间（手动撤销,过期关闭都要记录这个时间）
     */
    private Long closeTime;
    public void  setCloseTime(Long closeTime)
    {
        this.closeTime= closeTime;
        this.formatCloseTime = DateCustomUtils.formatToDateTimeString(closeTime);
    }

    /**
     * 格式化关闭时间（手动撤销,过期关闭都要记录这个时间）
     */
    @TableField(exist =  false)
    private String formatCloseTime;


    /**
     * 订单类型（0充值 1消费订单，2服务订单）
     */
    private OrderConstant.OrderType orderType;


    /**
     * 平台优惠券Id
     */
    private Long couponId = 0L;

    /**
     * 平台优惠券名称
     */
    private String couponName = "无可使用券";

    /**
     * 平台优惠券面额
     */
    private BigDecimal couponFaceValue = BigDecimal.ZERO;

    /**
     * 平台优惠券实际优惠多少(对于支付订单，店铺订单，实际的商品子订单)
     */
    private BigDecimal couponResultValue = BigDecimal.ZERO;

    /**
     * 商品分区特征(0,普通商品,1服务体系礼包,2新人福利区,3公益申领)
     */
    private GoodsConstant.AreaFeature areaFeature = GoodsConstant.AreaFeature.GENERAL;

    /**
     * 是否支付成功
     *
     * @return
     */
    @JsonIgnore
    public Boolean isPaySuccess() {
        return OrderConstant.PaymentStatus.SUCCESS.equals(this.getPaymentStatus());
    }

    /**
     * 是否实际支付成功
     *
     * @return
     */
    @JsonIgnore
    public Boolean isFactPaySuccess() {
        return OrderConstant.PaymentStatus.SUCCESS.equals(this.getPaymentStatus())
                || OrderConstant.PaymentStatus.SUCCESS_BUSINESS_ERROR_LAUNCH_REFUND.equals(this.getPaymentStatus())
                || OrderConstant.PaymentStatus.SUCCESS_BUSINESS_ERROR_REFUND_SUCCESS.equals(this.getPaymentStatus())
                || OrderConstant.PaymentStatus.SUCCESS_BUSINESS_ERROR_REFUND_FAIL.equals(this.getPaymentStatus());
    }

    /**
     * 是否还没有支付
     *
     * @return
     */
    @JsonIgnore
    public Boolean isNotPay() {
        return OrderConstant.PaymentStatus.NO_PAY.equals(this.getPaymentStatus());
    }

    /**
     * 是否支付失败
     *
     * @return
     */
    @JsonIgnore
    public Boolean isPayFail() {
        return OrderConstant.PaymentStatus.FAIL.equals(this.getPaymentStatus());
    }


    @Override
    public Long getIdentity() {
        return getId();
    }

    /**
     * 所有商品图片
     */
    @JsonIgnore
    private String goodsImagesValue = "";

    @TableField(exist = false)
    private List<String> goodsImages;

    public void setGoodsImages(List<String> goodsImages) {
        this.goodsImages = goodsImages;
        if(goodsImages.size()==0)
        {
            this.goodsImagesValue = "";
        }
        else
        {
            this.goodsImagesValue = JSONUtil.toJsonStr(this.goodsImages );
        }

    }
    /**
     * 把字符串映射成对象（多图）
     */
    public void setGoodsImagesValue(String goodsImagesValue) {
        this.goodsImagesValue = goodsImagesValue;
        if (StringUtils.isEmpty(this.goodsImagesValue)) {
            setGoodsImages(new ArrayList<>());
        } else {
            try {
                setGoodsImages(ClassConvertUtils.stringToClassSnake(goodsImagesValue, new TypeReference<List< String>>() {
                }));
            } catch (IOException e) {
                throw new RRException("图片无法转List");
            }

        }
    }

    @TableField(exist = false)
    private List<Order> orders;
    public  List<Order> loadOrders()
    {
        if(orders==null)
        {
            OrderService orderService  = (OrderService) SpringContextUtil.getBean("orderService");
            orders = orderService.loadByPayOrderId(this.getId());
        }
        return orders;
    }

    @TableField(exist = false)
    private Integer goodsNumber;
    public Integer loadGoodsNumber(){
        this.goodsNumber =  this.loadOrders().stream().mapToInt(Order::getGoodsNumber).sum();
        return goodsNumber;
    }

    public Long getNowMillis(){
        return System.currentTimeMillis();
    }

    /**
     * 真实姓名
     */
    @TableField(exist = false)
    private String realName;
    /**
     * 身份证号
     */
    @TableField(exist = false)
    private String idNo;

}
